home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / patch / util.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  378 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5. #include "backupfile.h"
  6.  
  7. /* Rename a file, copying it if necessary. */
  8.  
  9. int
  10. move_file(from,to)
  11. char *from, *to;
  12. {
  13.     char bakname[512];
  14.     Reg1 char *s;
  15.     Reg2 int i;
  16.     Reg3 int fromfd;
  17.  
  18.     /* to stdout? */
  19.  
  20.     if (strEQ(to, "-")) {
  21. #ifdef DEBUGGING
  22.     if (debug & 4)
  23.         say2("Moving %s to stdout.\n", from);
  24. #endif
  25.     fromfd = open(from, 0);
  26.     if (fromfd < 0)
  27.         fatal2("patch: internal error, can't reopen %s\n", from);
  28.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  29.         if (write(1, buf, i) != 1)
  30.         fatal1("patch: write failed\n");
  31.     Close(fromfd);
  32.     return 0;
  33.     }
  34.  
  35.     if (origprae) {
  36.     Strcpy(bakname, origprae);
  37.     Strcat(bakname, to);
  38.     } else {
  39. #ifndef NODIR
  40.     char *backupname = find_backup_file_name(to);
  41.     if (backupname == (char *) 0)
  42.         fatal1("Can't seem to get enough memory.\n");
  43.     Strcpy(bakname, backupname);
  44.     free(backupname);
  45. #else /* NODIR */
  46.     Strcpy(bakname, to);
  47.         Strcat(bakname, simple_backup_suffix);
  48. #endif /* NODIR */
  49.     }
  50.  
  51.     if (stat(to, &filestat) >= 0) {    /* output file exists */
  52.     dev_t to_device = filestat.st_dev;
  53.     ino_t to_inode  = filestat.st_ino;
  54.     char *simplename = bakname;
  55.     
  56.     for (s=bakname; *s; s++) {
  57.         if (*s == '/')
  58.         simplename = s+1;
  59.     }
  60.     /* Find a backup name that is not the same file.
  61.        Change the first lowercase char into uppercase;
  62.        if that isn't sufficient, chop off the first char and try again.  */
  63.     while (stat(bakname, &filestat) >= 0 &&
  64.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  65.         /* Skip initial non-lowercase chars.  */
  66.         for (s=simplename; *s && !islower(*s); s++) ;
  67.         if (*s)
  68.         *s = toupper(*s);
  69.         else
  70.         Strcpy(simplename, simplename+1);
  71.     }
  72.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  73. #ifdef DEBUGGING
  74.     if (debug & 4)
  75.         say3("Moving %s to %s.\n", to, bakname);
  76. #endif
  77.     if (link(to, bakname) < 0) {
  78.         say3("patch: can't backup %s, output is in %s\n",
  79.         to, from);
  80.         return -1;
  81.     }
  82.     while (unlink(to) >= 0) ;
  83.     }
  84. #ifdef DEBUGGING
  85.     if (debug & 4)
  86.     say3("Moving %s to %s.\n", from, to);
  87. #endif
  88.     if (link(from, to) < 0) {        /* different file system? */
  89.     Reg4 int tofd;
  90.     
  91.     tofd = creat(to, 0666);
  92.     if (tofd < 0) {
  93.         say3("patch: can't create %s, output is in %s.\n",
  94.           to, from);
  95.         return -1;
  96.     }
  97.     fromfd = open(from, 0);
  98.     if (fromfd < 0)
  99.         fatal2("patch: internal error, can't reopen %s\n", from);
  100.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  101.         if (write(tofd, buf, i) != i)
  102.         fatal1("patch: write failed\n");
  103.     Close(fromfd);
  104.     Close(tofd);
  105.     }
  106.     Unlink(from);
  107.     return 0;
  108. }
  109.  
  110. /* Copy a file. */
  111.  
  112. void
  113. copy_file(from,to)
  114. char *from, *to;
  115. {
  116.     Reg3 int tofd;
  117.     Reg2 int fromfd;
  118.     Reg1 int i;
  119.     
  120.     tofd = creat(to, 0666);
  121.     if (tofd < 0)
  122.     fatal2("patch: can't create %s.\n", to);
  123.     fromfd = open(from, 0);
  124.     if (fromfd < 0)
  125.     fatal2("patch: internal error, can't reopen %s\n", from);
  126.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  127.     if (write(tofd, buf, i) != i)
  128.         fatal2("patch: write (%s) failed\n", to);
  129.     Close(fromfd);
  130.     Close(tofd);
  131. }
  132.  
  133. /* Allocate a unique area for a string. */
  134.  
  135. char *
  136. savestr(s)
  137. Reg1 char *s;
  138. {
  139.     Reg3 char *rv;
  140.     Reg2 char *t;
  141.  
  142.     if (!s)
  143.     s = "Oops";
  144.     t = s;
  145.     while (*t++);
  146.     rv = malloc((MEM) (t - s));
  147.     if (rv == Nullch) {
  148.     if (using_plan_a)
  149.         out_of_mem = TRUE;
  150.     else
  151.         fatal1("patch: out of memory (savestr)\n");
  152.     }
  153.     else {
  154.     t = rv;
  155.     while (*t++ = *s++);
  156.     }
  157.     return rv;
  158. }
  159.  
  160. #if defined(lint) && defined(CANVARARG)
  161.  
  162. /*VARARGS ARGSUSED*/
  163. say(pat) char *pat; { ; }
  164. /*VARARGS ARGSUSED*/
  165. fatal(pat) char *pat; { ; }
  166. /*VARARGS ARGSUSED*/
  167. ask(pat) char *pat; { ; }
  168.  
  169. #else
  170.  
  171. /* Vanilla terminal output (buffered). */
  172.  
  173. void
  174. say(pat,arg1,arg2,arg3)
  175. char *pat;
  176. long arg1,arg2,arg3;
  177. {
  178.     fprintf(stderr, pat, arg1, arg2, arg3);
  179.     Fflush(stderr);
  180. }
  181.  
  182. /* Terminal output, pun intended. */
  183.  
  184. void                /* very void */
  185. fatal(pat,arg1,arg2,arg3)
  186. char *pat;
  187. long arg1,arg2,arg3;
  188. {
  189.     void my_exit();
  190.  
  191.     say(pat, arg1, arg2, arg3);
  192.     my_exit(1);
  193. }
  194.  
  195. /* Get a response from the user, somehow or other. */
  196.  
  197. void
  198. ask(pat,arg1,arg2,arg3)
  199. char *pat;
  200. long arg1,arg2,arg3;
  201. {
  202.     int ttyfd;
  203.     int r;
  204.     bool tty2 = isatty(2);
  205.  
  206.     Sprintf(buf, pat, arg1, arg2, arg3);
  207.     Fflush(stderr);
  208.     write(2, buf, strlen(buf));
  209.     if (tty2) {                /* might be redirected to a file */
  210.     r = read(2, buf, sizeof buf);
  211.     }
  212.     else if (isatty(1)) {        /* this may be new file output */
  213.     Fflush(stdout);
  214.     write(1, buf, strlen(buf));
  215.     r = read(1, buf, sizeof buf);
  216.     }
  217.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  218.                     /* might be deleted or unwriteable */
  219.     write(ttyfd, buf, strlen(buf));
  220.     r = read(ttyfd, buf, sizeof buf);
  221.     Close(ttyfd);
  222.     }
  223.     else if (isatty(0)) {        /* this is probably patch input */
  224.     Fflush(stdin);
  225.     write(0, buf, strlen(buf));
  226.     r = read(0, buf, sizeof buf);
  227.     }
  228.     else {                /* no terminal at all--default it */
  229.     buf[0] = '\n';
  230.     r = 1;
  231.     }
  232.     if (r <= 0)
  233.     buf[0] = 0;
  234.     else
  235.     buf[r] = '\0';
  236.     if (!tty2)
  237.     say1(buf);
  238. }
  239. #endif /* lint */
  240.  
  241. /* How to handle certain events when not in a critical region. */
  242.  
  243. void
  244. set_signals(reset)
  245. int reset;
  246. {
  247.     void my_exit();
  248. #ifndef lint
  249. #ifdef VOIDSIG
  250.     static void (*hupval)(),(*intval)();
  251. #else
  252.     static int (*hupval)(),(*intval)();
  253. #endif
  254.  
  255.     if (!reset) {
  256.     hupval = signal(SIGHUP, SIG_IGN);
  257.     if (hupval != SIG_IGN)
  258. #ifdef VOIDSIG
  259.         hupval = my_exit;
  260. #else
  261.         hupval = (int(*)())my_exit;
  262. #endif
  263.     intval = signal(SIGINT, SIG_IGN);
  264.     if (intval != SIG_IGN)
  265. #ifdef VOIDSIG
  266.         intval = my_exit;
  267. #else
  268.         intval = (int(*)())my_exit;
  269. #endif
  270.     }
  271.     Signal(SIGHUP, hupval);
  272.     Signal(SIGINT, intval);
  273. #endif
  274. }
  275.  
  276. /* How to handle certain events when in a critical region. */
  277.  
  278. void
  279. ignore_signals()
  280. {
  281. #ifndef lint
  282.     Signal(SIGHUP, SIG_IGN);
  283.     Signal(SIGINT, SIG_IGN);
  284. #endif
  285. }
  286.  
  287. /* Make sure we'll have the directories to create a file. */
  288.  
  289. void
  290. makedirs(filename,striplast)
  291. Reg1 char *filename;
  292. bool striplast;
  293. {
  294.     char tmpbuf[256];
  295.     Reg2 char *s = tmpbuf;
  296.     char *dirv[20];
  297.     Reg3 int i;
  298.     Reg4 int dirvp = 0;
  299.  
  300.     while (*filename) {
  301.     if (*filename == '/') {
  302.         filename++;
  303.         dirv[dirvp++] = s;
  304.         *s++ = '\0';
  305.     }
  306.     else {
  307.         *s++ = *filename++;
  308.     }
  309.     }
  310.     *s = '\0';
  311.     dirv[dirvp] = s;
  312.     if (striplast)
  313.     dirvp--;
  314.     if (dirvp < 0)
  315.     return;
  316.     strcpy(buf, "mkdir");
  317.     s = buf;
  318.     for (i=0; i<=dirvp; i++) {
  319.     while (*s) s++;
  320.     *s++ = ' ';
  321.     strcpy(s, tmpbuf);
  322.     *dirv[i] = '/';
  323.     }
  324.     system(buf);
  325. }
  326.  
  327. /* Make filenames more reasonable. */
  328.  
  329. char *
  330. fetchname(at,strip_leading,assume_exists)
  331. char *at;
  332. int strip_leading;
  333. int assume_exists;
  334. {
  335.     char *s;
  336.     char *name;
  337.     Reg1 char *t;
  338.     char tmpbuf[200];
  339.  
  340.     if (!at)
  341.     return Nullch;
  342.     s = savestr(at);
  343.     for (t=s; isspace(*t); t++) ;
  344.     name = t;
  345. #ifdef DEBUGGING
  346.     if (debug & 128)
  347.     say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
  348. #endif
  349.     if (strnEQ(name, "/dev/null", 9))    /* so files can be created by diffing */
  350.     return Nullch;            /*   against /dev/null. */
  351.     for (; *t && !isspace(*t); t++)
  352.     if (*t == '/')
  353.         if (--strip_leading >= 0)
  354.         name = t+1;
  355.     *t = '\0';
  356.     if (name != s && *s != '/') {
  357.     name[-1] = '\0';
  358.     if (stat(s, &filestat) == 0 && (filestat.st_mode & S_IFDIR)) {
  359.         name[-1] = '/';
  360.         name=s;
  361.     }
  362.     }
  363.     name = savestr(name);
  364.     Sprintf(tmpbuf, "RCS/%s", name);
  365.     free(s);
  366.     if (stat(name, &filestat) < 0 && !assume_exists) {
  367.     Strcat(tmpbuf, RCSSUFFIX);
  368.     if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
  369.         Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
  370.         if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
  371.         free(name);
  372.         name = Nullch;
  373.         }
  374.     }
  375.     }
  376.     return name;
  377. }
  378.